package my.avoskagae.store.gaejdo;

import java.util.ArrayList;
import java.util.List;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;
import javax.jdo.Transaction;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;


import my.avoskagae.model.AvoskaModelException;
import my.avoskagae.model.entity.Product;
import my.avoskagae.store.abstr.StoreAdapter;
import my.avoskagae.store.gaejdo.entity.ProductImpl;
import my.avoskagae.store.gaejdo.entity.UserDataStoreImpl;

public class JDOStoreAdapterImpl implements StoreAdapter {

	private static final PersistenceManagerFactory PMF = JDOHelper.getPersistenceManagerFactory("transactions-optional");

	private UserDataStoreImpl getCurentUserDataStore(PersistenceManager pm) throws AvoskaModelException{
		UserService userService = UserServiceFactory.getUserService();
        User user = userService.getCurrentUser();
        if (user==null) {
        	throw new AvoskaModelException("User must be authenticate");
        }
        String userId = user.getUserId();
        
        System.out.println(user.getNickname()+" "+user.getEmail()+" "+user.getUserId());
        
        Query q = pm.newQuery(UserDataStoreImpl.class);
//        q.setFilter("userId==\""+userId+"\"");
        q.setFilter("userId == userIdParam");
        q.declareParameters("String userIdParam");
        List<UserDataStoreImpl> luds = (List<UserDataStoreImpl>) q.execute(userId);
        UserDataStoreImpl uds;
        if (luds.isEmpty()){
        	uds = new UserDataStoreImpl();
        	uds.setUserId(userId);
        	pm.makePersistent(uds);
        } else {
        	uds = luds.get(0);
        }
        return uds;
	}
	
	@Override
	public List<Product> getProducts() throws AvoskaModelException {
		//TODO Как работать со старыми версиями объектов? (после обновления классов, после обновления библиотек GAE)
		PersistenceManager pm = PMF.getPersistenceManager();
		UserDataStoreImpl us = getCurentUserDataStore(pm);
		List<ProductImpl> ls = us.getProducts();
		List<Product> lr = new ArrayList<Product>();
		for (Product p : ls) {
			lr.add(pm.detachCopy(p));
		}
		pm.close();
		return lr;
	}
	
	@Override
	public Product createProduct(String name) throws AvoskaModelException{
		PersistenceManager pm = PMF.getPersistenceManager();
		Transaction tx = pm.currentTransaction();
		tx.begin();
		
		ProductImpl p = new ProductImpl();
		p.setName(name);
		
		UserDataStoreImpl us = getCurentUserDataStore(pm);
		us.getProducts().add(p);
		pm.makePersistent(us);
		
		tx.commit();

		p = pm.detachCopy(p);
		
		pm.close();
		return p;
	}
	
	@Override
	public boolean removeProduct(Product product) throws AvoskaModelException {
		//FIXME последнее удаление перед остановкой сервера не сохраняется, 
				// видимо дело в не закрытой транзакции, после старта сервера запись снова на месте
		PersistenceManager pm = PMF.getPersistenceManager();
		UserDataStoreImpl us = getCurentUserDataStore(pm);
		us.getProducts().remove(product);
		pm.makePersistent(us);
		pm.close();
		return true;
	}

	@Override
	public boolean updateProduct(Product product) {
		PersistenceManager pm = PMF.getPersistenceManager();
		pm.makePersistent(product);
		pm.close();
		return true;
	}

	@Override
	public Product findPrductByName(String name) throws AvoskaModelException {
		PersistenceManager pm = PMF.getPersistenceManager();
		Query q = pm.newQuery(ProductImpl.class);
		String k = getCurentUserDataStore(pm).getKey();
//		q.setFilter("name==\""+name+"\" && userDataStore==\""+k+"\"");
		q.setFilter("name == nameParam && userDataStore == userDataStoreParam");
		q.declareParameters("String nameParam, String userDataStoreParam");
		
		List<Product> res = (List<Product>) q.execute(name, k);
		Product p = null;
		if (!res.isEmpty()){
			p = res.get(0);
		}
		pm.close();
		return p;
	}

}
